#include <iostream>
#include <string>

class Attribute {
 public:
  Attribute() {
    // ...
    std::cout << "Call Attribute()" << std::endl;
  }

  Attribute(const Attribute& o) {
    // ...
    std::cout << "Call Attribute(Attribute&)" << std::endl;
  }

  Attribute(Attribute&& o) {
    // ...
    std::cout << "Call Attribute(Attribute&&)" << std::endl;
  }

  ~Attribute() {
    // ~Actor
    std::cout << "Call ~Attribute()" << std::endl;
  }
};

class Actor {
 public:
  Actor(const int& x) : px(x) {
    // ...
    std::cout << "Call Acotr(int&) px=" << px << std::endl;
  }

  Actor(int&& x) : px(x) {
    // ...
    std::cout << "Call Acotr(int&&) px=" << px << std::endl;
  }

  ~Actor() {
    // ~Actor
    std::cout << "Call ~Actor() px=" << px << std::endl;
  }

 private:
  int px;
};

class Player : public Actor {
 public:
  Player(const int& x, const Attribute& name) : Actor(x), attr(name) {
    // ...
    std::cout << "Call Player(int&, std::string&)" << std::endl;
  }

  //   // 初始化列表没有使用 std::move，触发普通的拷贝构造
  //   Player(int&& x, Attribute&& name) : Actor(x), attr(name) {
  //     ///
  //     std::cout << "Call Player(int&&, std::string&&)" << std::endl;
  //   }

  // 定义了移动构造，优先使用移动构造，
  // 否则，再使用 const T& 拷贝构造
  // 
  // 组合或者继承时，显式调用 std::move
  // 成员变量和父类的初始化需要 std::move, 否则调用的构造函数将是普通的拷贝构造
  Player(int&& x, Attribute&& name)
      : Actor(std::move(x)), attr(std::move(name)) {
    /// 注意： 此处 name 可能已经无效，参见 test04.cpp
    std::cout << "Call Player(int&&, std::string&&)" << std::endl;
  }

  ~Player() {
    // ~Actor
    std::cout << "Call ~Player()" << std::endl;
  }

 private:
  std::string name;
  Attribute attr;
};

int main() {
  int x1 = 10;
  std::string p1Name = "PlayerA";
  Attribute attr1;
  Player p1(x1, attr1);  // 使用拷贝构造： Player(int& x, std::string& name)
  std::cout << "----------line 1-------\n";
  // std::move 本质是进行了类型转换：
  // Tp&& move(_Tp && __t) { return static_cast<_Tp&&>(__t) };
  Player p11(std::move(x1), std::move(attr1));  // 使用移动构造
  std::cout << "----------line 2-------\n";
  Player p2(20, Attribute());  // 使用移动构造
  std::cout << "----------End!-------\n";

  return 0;
}
